package me.zhengjie.timing.plc;

import lombok.RequiredArgsConstructor;
import me.zhengjie.WcsReport.WcsReportService;
import me.zhengjie.agvSend.AgvSendService;
import me.zhengjie.pojo.dto.*;
import me.zhengjie.pojo.entity.IwsSOutside;
import me.zhengjie.pojo.entity.MaterialDao;
import me.zhengjie.pojo.entity.NestingMiddleTable;
import me.zhengjie.pojo.entity.WcsInboundMission;
import me.zhengjie.pojo.vo.AgvTaskSubmitVo;
import me.zhengjie.pojo.vo.TestVo;
import me.zhengjie.sqlservice.*;
import me.zhengjie.tcp.CircleLibraryTCP;
import me.zhengjie.util.state.MaterialStatus;
import me.zhengjie.util.state.TaskStatus;
import me.zhengjie.util.state.TaskType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;

@Component
@RequiredArgsConstructor
public class CircleLibraryTiming {

    private static final Logger chainLine = LoggerFactory.getLogger("chainLine");

    private final IwsWareHouseService iwsWareHouseService;

    private final CircleLibraryTCP circleLibraryTCP;

    private final AgvSendService agvSendService;

    private final WcsInboundMissionService wcsInboundMissionService;

    private final IwsSOutsideService iwsSOutsideService;

    private final WcsReportService wcsReportService;

    private final NestingMiddleTableService nestingMiddleTableService;

    @Transactional
//    @Scheduled(fixedDelay = 1000)
    public void circleLibrary(){

            IwsSOutside iwsSOutsides = iwsSOutsideService.selectCircleLibrary(TaskType.STORAGE_TYPE_ONE_FLOOR_CIRCLE_LIBRARY.getMessage(), 3);
            if (iwsSOutsides != null){
                String id = iwsSOutsides.getId();
                //通知PLC到达储位
                boolean b3 = circleLibraryTCP.writeWithRetry(510, 1, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), 3);
                //通知PLC开始测高
                boolean b = circleLibraryTCP.writeWithRetry(512, 1, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), 3);
                if (b){
                    //获取读码状态
                    Integer i = circleLibraryTCP.readHoldingRegisters(11,  MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus());
                    if (i == 1){
                        //获取读码结果
                        String palletCode = circleLibraryTCP.readHoldingRegistersString(12, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus());
                        //查询任务获取任务id
                        List<WcsInboundMission> wcsInboundMissionList = wcsInboundMissionService.selectContainerCodeUpdateDesc(palletCode);
//                        WcsInboundMission wcsInboundMission = wcsInboundMissionService.selectContainerCode(palletCode);
                        if (!wcsInboundMissionList.isEmpty()){
                            WcsInboundMission wcsInboundMission = wcsInboundMissionList.get(0);
                            String inboundCode = wcsInboundMission.getInboundCode();

                            //检测高度
                            Integer tall = circleLibraryTCP.readHoldingRegisters(31,  MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus());
                            if (tall == 2){
                                //测高完成，获取测高结果
                                Integer tallResult = circleLibraryTCP.readHoldingRegisters(30,  MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus());
                                if (tallResult != 0 && tallResult !=4){
                                    //1.发送wms查看栈板是否已入库
                                    InboundIsCodeExistDto inboundIsCodeExist = new InboundIsCodeExistDto();
                                    inboundIsCodeExist.setContainerCode(palletCode);
                                    inboundIsCodeExist.setNest(true);
                                    boolean exist = wcsReportService.inboundIsCodeExist(inboundIsCodeExist);
                                    if (exist) {
                                        circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_MATERIAL_EXIST.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                    }else {
                                        //2.查询嵌套信息是有嵌套
//                                        ReturnVo returnVo = wcsReportService.middleNestingData(palletCode);
                                        List<NestingMiddleTable> nestingMiddleTables = nestingMiddleTableService.selectContainerCode(palletCode);
                                        if (nestingMiddleTables.isEmpty()){
                                            circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_NO.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                        }else {
                                                //3.对比MES信息和WMS库存信息是否一致
                                            TestVo testVo = wcsReportService.wmsInventoryInformation(palletCode);
                                            if (testVo.getCode() !=200){
                                                    circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_WMS_INVENTORY_INFORMATION_NO.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                }else {
                                                    //对比库存信息 对比物料条码和数量
//                                                    ArrayList<MiddleTable> mesMiddleTableList = (ArrayList<MiddleTable>) returnVo.getData();
                                                List<MaterialDao> materialDaoList = testVo.getData();
                                                HashSet<InventoryContrast> mesInventorySet = new HashSet<>();
                                                    HashSet<InventoryContrast> wmsInventorySet = new HashSet<>();
//                                                    BeanUtils.copyProperties(nestingMiddleTables,mesInventorySet);
//                                                    BeanUtils.copyProperties(wmsInventoryList,wmsInventorySet);
                                                    for (MaterialDao datum : materialDaoList) {
                                                        InventoryContrast wmsInventory = new InventoryContrast();
                                                        BeanUtils.copyProperties(datum,wmsInventory);
                                                        wmsInventorySet.add(wmsInventory);
                                                    }
                                                    for (NestingMiddleTable middleTable : nestingMiddleTables) {
                                                        InventoryContrast wmsInventory = new InventoryContrast();
                                                        BeanUtils.copyProperties(middleTable,wmsInventory);
                                                        mesInventorySet.add(wmsInventory);
                                                    }
                                                    if (!mesInventorySet.equals(wmsInventorySet)){
                                                        //WMS和WES库存信息不一致
                                                        circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_MES_AND_WMS_INVENTORY_NO.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                    }else {
                                                        //库存信息一致，获取终点储位
                                                        //3获取终点储位
                                                        InboundStorageApplyDto1 inboundStorageApplyDto = new InboundStorageApplyDto1();
                                                        inboundStorageApplyDto.setContainerCode(palletCode);
                                                        inboundStorageApplyDto.setFloor(String.valueOf(TaskType.ONE_FLOOR.getMessage()));
                                                        inboundStorageApplyDto.setNest(true);
                                                        inboundStorageApplyDto.setData(null);
                                                        //发送WMS申请入库请求终点储位
                                                        String destinationStorageCode = wcsReportService.inboundStorageApply(inboundStorageApplyDto);
                                                        if (destinationStorageCode != null){
                                                            //下发AGV继续执行任务指令
                                                            AGVTaskContinueExecuteDto agvTaskContinueExecuteDto = new AGVTaskContinueExecuteDto();
                                                            agvTaskContinueExecuteDto.setTriggerType("TASK");
                                                            agvTaskContinueExecuteDto.setTriggerCode(inboundCode);
                                                            ContinueExecute continueExecute = new ContinueExecute();
                                                            continueExecute.setSeq(0);
                                                            continueExecute.setType(TaskType.STORAGE.getMessage());
                                                            continueExecute.setCode(destinationStorageCode);
                                                            agvTaskContinueExecuteDto.setTargetRoute(continueExecute);
                                                            boolean b1 = agvSendService.taskContinueExecute(agvTaskContinueExecuteDto);
                                                            if (b1){
                                                                //通知plc离开
                                                                circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_YES.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                                //修改任务终点
                                                                boolean b4 = wcsInboundMissionService.updateDestination(inboundCode,destinationStorageCode);
                                                                if (!b4){
                                                                    chainLine.error("修改1楼回库终点储位失败，数据库异常");
                                                                    throw new RuntimeException("修改1楼回库终点储位失败，数据库异常");
                                                                }
                                                                //釋放儲位
                                                                iwsSOutsideService.updateStatus(id, null, 0);
                                                            }
                                                        }else {
                                                            //终点储位申请失败，取消任务
                                                            circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_STORAGE_LOCATION_NOT_FOUND.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                            //agv任务取消
                                                            TaskCancelDto taskCancelDto = new TaskCancelDto();
                                                            taskCancelDto.setRobotTaskCode(inboundCode);
                                                            taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                                            AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                                            if ("SUCCESS".equals(agvTaskSubmitVo.getCode())){
                                                                wcsInboundMissionService.updateMissionStatus(inboundCode,TaskStatus.task_abnormal.getStatus());
                                                                //釋放儲位
                                                                iwsSOutsideService.updateStatus(id, null, 0);
                                                            }
                                                        }
                                                    }
                                                }
                                        }
                                    }
                                } else if (tallResult == 4) {
                                    //agv任务取消
                                    TaskCancelDto taskCancelDto = new TaskCancelDto();
                                    taskCancelDto.setRobotTaskCode(inboundCode);
                                    taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                    AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                    if ("SUCCESS".equals(agvTaskSubmitVo.getCode())){
                                        wcsInboundMissionService.updateMissionStatus(inboundCode,TaskStatus.task_abnormal.getStatus());
                                        //釋放儲位
                                        iwsSOutsideService.updateStatus(id, null, 0);
                                    }
                                    //修改任务状态异常
                                    //通知AGV解绑储位
//                                    CarrierUnbindDto carrierUnbindDto = new CarrierUnbindDto();
//                                    carrierUnbindDto.setSlotCategory(TaskType.SITE.getMessage());
//                                    carrierUnbindDto.setSlotCode(TaskType.ONE_FLOOR_RETURN_TO_STORAGE_LOCATION.getMessage());
//                                    carrierUnbindDto.setCarrierCategory("PALLET");
//                                    carrierUnbindDto.setCarrierType("1");
//                                    carrierUnbindDto.setInvoke(TaskType.UNBIND.getMessage());
//                                    agvSendService.carrierUnbind(carrierUnbindDto);
                                }
                            }else if (tall > 2){
                                //测高状态异常，释放储位
                                //agv任务取消
                                TaskCancelDto taskCancelDto = new TaskCancelDto();
                                taskCancelDto.setRobotTaskCode(inboundCode);
                                taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                if ("SUCCESS".equals(agvTaskSubmitVo.getCode())){
                                    wcsInboundMissionService.updateMissionStatus(inboundCode,TaskStatus.task_abnormal.getStatus());
                                    //釋放儲位
                                    iwsSOutsideService.updateStatus(id, null, 0);
                                }
                            }
                        }else {
                            //返回失败
                            circleLibraryTCP.writeWithRetry(00, 4,  MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), 3);
                        }
                    }else if (i ==2 || i ==3){
                        //讀碼失敗释放储位
//                        boolean b1 = iwsSOutsideService.updateStatus(id, null, 0);
                    }
                }

            }
    }
}
